#include "pluginmanager.h"
#include <QCoreApplication>
#include <QDirIterator>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QMessageBox>
#include <QDebug>

PluginManager::PluginManager(QObject *parent) : QObject(parent),
    m_pluginsDir(QCoreApplication::applicationDirPath() + QDir::separator() + "plugins")
{
}

PluginManager::~PluginManager()
{
    unloadAllPlugins();
}

bool PluginManager::initialize(const QString &pluginsDir, const QStringList &enabledPlugins)
{
    m_pluginsDir = pluginsDir;
    m_enabledPlugins = enabledPlugins;

    // 确保插件目录存在
    QDir dir(m_pluginsDir);
    if (!dir.exists() && !dir.mkpath(".")) {
        qWarning() << "Failed to create plugins directory:" << m_pluginsDir;
        return false;
    }

    loadPlugins();
    return true;
}

void PluginManager::loadPlugins()
{
    // 先卸载所有已加载插件
    unloadAllPlugins();

    // 扫描插件目录
    QStringList pluginFiles = scanPluginsDirectory();
    if (pluginFiles.isEmpty()) {
        qDebug() << "No plugin files found in:" << m_pluginsDir;
        return;
    }

    // 加载启用的插件
    for (const QString &filePath : pluginFiles) {
        QFileInfo fileInfo(filePath);
        QString pluginName = fileInfo.baseName();

        // 检查是否启用
        if (m_enabledPlugins.isEmpty() || m_enabledPlugins.contains(pluginName)) {
            loadPlugin(filePath);
        }
    }
}

bool PluginManager::loadPlugin(const QString &pluginPath)
{
    QFileInfo fileInfo(pluginPath);
    if (!fileInfo.exists() || !fileInfo.isFile()) {
        qWarning() << "Plugin file not found:" << pluginPath;
        return false;
    }

    QString pluginName = fileInfo.baseName();

    // 检查是否已加载
    if (m_pluginLoaders.contains(pluginName)) {
        qDebug() << "Plugin already loaded:" << pluginName;
        return true;
    }

    // 创建插件加载器
    QPluginLoader *loader = new QPluginLoader(pluginPath, this);
    QObject *pluginInstance = loader->instance();

    if (!pluginInstance) {
        qWarning() << "Failed to load plugin:" << pluginName << "Error:" << loader->errorString();
        delete loader;
        return false;
    }

    // 检查是否实现了插件接口
    MarkdownPlugin *plugin = qobject_cast<MarkdownPlugin*>(pluginInstance);
    if (!plugin) {
        qWarning() << "Plugin does not implement MarkdownPlugin interface:" << pluginName;
        delete loader;
        return false;
    }

    // 获取插件元数据
    QVariantMap metadata = getPluginMetadata(*loader);

    // 检查兼容性
    if (!checkPluginCompatibility(plugin, metadata)) {
        qWarning() << "Plugin incompatible:" << pluginName;
        delete loader;
        return false;
    }

    // 初始化插件
    QVariantMap initArgs;
    initArgs["appPath"] = QCoreApplication::applicationDirPath();
    initArgs["configPath"] = QCoreApplication::applicationDirPath() + QDir::separator() + "plugins_config";

    if (!plugin->initialize(initArgs)) {
        qWarning() << "Failed to initialize plugin:" << pluginName;
        delete loader;
        return false;
    }

    // 连接插件信号
    connect(plugin, &MarkdownPlugin::statusChanged, this, &PluginManager::onPluginStatusChanged);
    connect(plugin, &MarkdownPlugin::operationCompleted, this, &PluginManager::onPluginOperationCompleted);

    // 存储插件信息
    m_pluginLoaders[pluginName] = loader;
    m_plugins[pluginName] = plugin;
    m_pluginMetadata[pluginName] = metadata;
    m_pluginPaths[pluginName] = pluginPath;

    qDebug() << "Successfully loaded plugin:" << pluginName;
    emit pluginLoaded(pluginName);
    return true;
}

bool PluginManager::unloadPlugin(const QString &pluginName)
{
    if (!m_pluginLoaders.contains(pluginName)) {
        qDebug() << "Plugin not loaded:" << pluginName;
        return false;
    }

    // 获取插件加载器
    QPluginLoader *loader = m_pluginLoaders[pluginName];

    // 断开信号连接
    MarkdownPlugin *plugin = m_plugins[pluginName];
    if (plugin) {
        disconnect(plugin, nullptr, this, nullptr);
    }

    // 卸载插件
    bool unloaded = loader->unload();
    if (!unloaded) {
        qWarning() << "Failed to unload plugin:" << pluginName << "Error:" << loader->errorString();
    }

    // 清理资源
    delete loader;
    m_pluginLoaders.remove(pluginName);
    m_plugins.remove(pluginName);
    m_pluginMetadata.remove(pluginName);
    m_pluginPaths.remove(pluginName);

    qDebug() << "Plugin unloaded:" << pluginName;
    emit pluginUnloaded(pluginName);
    return unloaded;
}

void PluginManager::unloadAllPlugins()
{
    QStringList pluginNames = m_pluginLoaders.keys();
    for (const QString &name : pluginNames) {
        unloadPlugin(name);
    }
}

void PluginManager::enablePlugin(const QString &pluginName)
{
    if (!m_enabledPlugins.contains(pluginName)) {
        m_enabledPlugins.append(pluginName);
        loadPlugins(); // 重新加载所有插件
    }
}

void PluginManager::disablePlugin(const QString &pluginName)
{
    if (m_enabledPlugins.removeAll(pluginName) > 0) {
        unloadPlugin(pluginName);
    }
}

bool PluginManager::isPluginLoaded(const QString &pluginName) const
{
    return m_pluginLoaders.contains(pluginName);
}

bool PluginManager::isPluginEnabled(const QString &pluginName) const
{
    return m_enabledPlugins.contains(pluginName);
}

QStringList PluginManager::loadedPlugins() const
{
    return m_pluginLoaders.keys();
}

QStringList PluginManager::enabledPlugins() const
{
    return m_enabledPlugins;
}

QStringList PluginManager::availablePlugins() const
{
    QStringList result;
    QStringList pluginFiles = scanPluginsDirectory();

    for (const QString &filePath : pluginFiles) {
        QFileInfo fileInfo(filePath);
        result.append(fileInfo.baseName());
    }

    return result;
}

QVariantMap PluginManager::getPluginInfo(const QString &pluginName) const
{
    if (m_pluginMetadata.contains(pluginName)) {
        return m_pluginMetadata[pluginName];
    }

    return QVariantMap();
}

MarkdownPlugin *PluginManager::getPlugin(const QString &pluginName) const
{
    if (m_plugins.contains(pluginName)) {
        return m_plugins[pluginName];
    }

    return nullptr;
}

QStringList PluginManager::getPluginsByType(MarkdownPlugin::PluginType type) const
{
    QStringList result;

    for (auto it = m_plugins.constBegin(); it != m_plugins.constEnd(); ++it) {
        if (it.value()->type() == type) {
            result.append(it.key());
        }
    }

    return result;
}

QVariant PluginManager::performPluginOperation(const QString &pluginName, const QString &operation, const QVariantMap &params)
{
    MarkdownPlugin *plugin = getPlugin(pluginName);
    if (!plugin) {
        qWarning() << "Plugin not found:" << pluginName;
        emit pluginError(pluginName, tr("Plugin not found"));
        return QVariant();
    }

    // 检查是否支持该操作
    if (!plugin->supportedOperations().contains(operation)) {
        qWarning() << "Plugin" << pluginName << "does not support operation:" << operation;
        emit pluginError(pluginName, tr("Operation not supported: %1").arg(operation));
        return QVariant();
    }

    // 执行操作
    return plugin->performOperation(operation, params);
}

void PluginManager::setPluginsDirectory(const QString &dir)
{
    if (m_pluginsDir != dir) {
        m_pluginsDir = dir;
        loadPlugins();
    }
}

void PluginManager::onPluginStatusChanged(const QString &message, int progress)
{
    MarkdownPlugin *plugin = qobject_cast<MarkdownPlugin*>(sender());
    if (!plugin) return;

    QString pluginName = plugin->name();
    emit pluginStatusChanged(pluginName, message);

    if (progress >= 0 && progress <= 100) {
        qDebug() << "Plugin" << pluginName << "progress:" << progress << "% -" << message;
    } else {
        qDebug() << "Plugin" << pluginName << ":" << message;
    }
}

void PluginManager::onPluginOperationCompleted(const QString &operation, bool success, const QVariant &result)
{
    MarkdownPlugin *plugin = qobject_cast<MarkdownPlugin*>(sender());
    if (!plugin) return;

    QString pluginName = plugin->name();
    emit pluginOperationCompleted(pluginName, operation, success, result);

    if (success) {
        qDebug() << "Plugin" << pluginName << "operation" << operation << "completed successfully";
    } else {
        qWarning() << "Plugin" << pluginName << "operation" << operation << "failed";
    }
}

QStringList PluginManager::scanPluginsDirectory() const
{
    QStringList result;

    if (m_pluginsDir.isEmpty()) {
        return result;
    }

    QDir dir(m_pluginsDir);
    if (!dir.exists()) {
        return result;
    }

    // 根据平台筛选插件文件
#ifdef Q_OS_WIN
    QString filter = "*.dll";
#elif Q_OS_MAC
    QString filter = "*.dylib";
#else
    QString filter = "*.so";
#endif

    // 查找所有插件文件
    QDirIterator it(dir.absolutePath(), QStringList() << filter, QDir::Files);
    while (it.hasNext()) {
        result.append(it.next());
    }

    return result;
}

QVariantMap PluginManager::getPluginMetadata(QPluginLoader &loader) const
{
    QVariantMap result;

    // 从JSON文件获取元数据
    QFileInfo fileInfo(loader.fileName());
    QString metaDataPath = fileInfo.path() + QDir::separator() + fileInfo.baseName() + ".json";

    QFile metaFile(metaDataPath);
    if (metaFile.exists() && metaFile.open(QIODevice::ReadOnly)) {
        QJsonDocument doc = QJsonDocument::fromJson(metaFile.readAll());
        if (doc.isObject()) {
            result = doc.object().toVariantMap();
        }
        metaFile.close();
    }

    // 从插件实例获取信息
    MarkdownPlugin *plugin = qobject_cast<MarkdownPlugin*>(loader.instance());
    if (plugin) {
        if (result["name"].toString().isEmpty()) result["name"] = plugin->name();
        if (result["displayName"].toString().isEmpty()) result["displayName"] = plugin->displayName();
        if (result["description"].toString().isEmpty()) result["description"] = plugin->description();
        if (result["version"].toString().isEmpty()) result["version"] = plugin->version();
        if (result["author"].toString().isEmpty()) result["author"] = plugin->author();
        result["type"] = plugin->type();
        result["supportedOperations"] = plugin->supportedOperations();
    }

    return result;
}

bool PluginManager::checkPluginCompatibility(MarkdownPlugin *plugin, const QVariantMap &metadata)
{
    Q_UNUSED(metadata);

    // 检查版本兼容性
    QString version = plugin->version();
    QRegularExpression versionRegex("^(\d+)\.(\d+)\.(\d+)$");
    QRegularExpressionMatch match = versionRegex.match(version);

    if (!match.hasMatch()) {
        qWarning() << "Invalid version format for plugin" << plugin->name() << ":" << version;
        return false;
    }

    // 这里可以添加更复杂的兼容性检查
    return true;
}